﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Data.Common;
using System.Linq;
namespace Gaea
{
    public static class GaeaExtension
    {

        /// <summary>
        /// 容器根基根节点
        /// </summary>
        internal static IServiceProvider ServiceProviderRoot { get; private set; }

        private static T GetServiceFromCollection<T>(this IServiceCollection services)
        {
            return (T)services.GetServiceFromCollection(typeof(T));
        }

        private static object GetServiceFromCollection(this IServiceCollection services, Type type)
        {
            return services
                .LastOrDefault(d => d.ServiceType == type)
                ?.ImplementationInstance;
        }

        public static IServiceCollection AddGaea<TDbConnection>(this IServiceCollection serviceCollection, IGaeaAdapter gaeaAdapter, bool isDefault = true, IGaeaOptionCache gaeaOptionCache = null, IGaeaConnectionFactory gaeaConnectionFactory = null) where TDbConnection : DbConnection
        {
            serviceCollection.AddTransient(typeof(IGaeaAdapter), gaeaAdapter.GetType());
            GaeaSuperPower.SetCommandBuilder(typeof(TDbConnection), gaeaAdapter, isDefault);
            serviceCollection.AddTransient<TDbConnection>();
            return serviceCollection.AddGaea(gaeaOptionCache, gaeaConnectionFactory);
        }

        public static IServiceCollection AddGaea(this IServiceCollection serviceCollection, IGaeaOptionCache gaeaOptionCache = null, IGaeaConnectionFactory gaeaConnectionFactory = null)
        {
            if (gaeaOptionCache == null)
            {
                serviceCollection.AddSingleton(typeof(IGaeaOptionCache), typeof(GaeaOptionCache));
            }
            else
            {

                serviceCollection.AddSingleton(typeof(IGaeaOptionCache), gaeaOptionCache.GetType());

            }
            if (gaeaConnectionFactory == null)
            {
                serviceCollection.AddSingleton(typeof(IGaeaConnectionFactory), typeof(GaeaConnectionFactory));
            }
            else
            {
                serviceCollection.AddSingleton(typeof(IGaeaConnectionFactory), gaeaConnectionFactory.GetType());
            }
            return serviceCollection;
        }

        //public static IServiceCollection AddGaeaOption(this IServiceCollection serviceCollection, Func<GaeaOption> optionConfiguration)
        //{
        //    var gaeaOption = optionConfiguration.Invoke();
        //    if (!typeof(DbConnection).IsAssignableFrom(gaeaOption.TypeOfDbConnection))
        //    {
        //        throw new ArgumentException($"{nameof(gaeaOption.TypeOfDbConnection)} must inherit from DbConnection");
        //    }
        //    var gaeaOptionCache = GetServiceFromCollection<IGaeaOptionCache>(serviceCollection);

        //    if (gaeaOptionCache == null)
        //    {
        //        gaeaOptionCache = new GaeaOptionCache();
        //    }
        //    gaeaOptionCache.AddGaeaOption(gaeaOption);
        //    serviceCollection.TryAddSingleton(gaeaOptionCache);

        //    if (serviceCollection.GetServiceFromCollection(gaeaOption.TypeOfDbConnection) == null)
        //    {
        //        serviceCollection.AddTransient(gaeaOption.TypeOfDbConnection);
        //    }

        //    if (serviceCollection.GetServiceFromCollection<IGaeaConnectionFactory>() == null)
        //    {
        //        serviceCollection.AddGaeaFactory<GaeaConnectionFactory>();
        //    }
        //    return serviceCollection;
        //}

        //public static IServiceCollection AddGaeaFactory<T>(this IServiceCollection serviceCollection) where T : IGaeaConnectionFactory
        //{
        //    serviceCollection.AddTransient(typeof(IGaeaConnectionFactory), typeof
        //        (T));
        //    return serviceCollection;
        //}

        //public static IServiceCollection AddGaeaAdapter<TDbConnection, TAdapter>(this IServiceCollection serviceCollection, bool isDefault = false) where TDbConnection : IDbConnection where TAdapter : IGaeaAdapter
        //{
        //    serviceCollection.AddTransient(typeof(IGaeaAdapter), typeof(TAdapter));
        //    GaeaSuperPower.SetCommandBuilder(typeof(TDbConnection), Activator.CreateInstance<TAdapter>(), isDefault);
        //    return serviceCollection;
        //}

        public static IServiceProvider AddGaeaOption(this IServiceProvider serviceProvider, Func<GaeaOption> optionConfiguration)
        {
            var gaeaOption = optionConfiguration.Invoke();
            if (!typeof(DbConnection).IsAssignableFrom(gaeaOption.TypeOfDbConnection))
            {
                throw new ArgumentException($"{nameof(gaeaOption.TypeOfDbConnection)} must inherit from DbConnection");
            }
            var gaeaOptionCache = serviceProvider.GetRequiredService<IGaeaOptionCache>();
            gaeaOptionCache.AddGaeaOption(gaeaOption);
            ServiceProviderRoot = serviceProvider;
            return serviceProvider;
        }

        //public static void UseGaea(this IServiceProvider serviceProvider)
        //{
        //    ServiceProviderRoot = serviceProvider;
        //}
    }
}
